package com.common.boot.service;

import org.locationtech.proj4j.*;

public interface ICoordTransformService {
  /** The constant x_PI. */
  Double XPI = 3.14159265358979324 * 3000.0 / 180.0;

  /** The constant PI. */
  Double PI = 3.1415926535897932384626;

  /** The constant a. */
  Double A = 6378245.0;

  /** The constant ee. */
  Double EE = 0.00669342162296594323;

  /** The constant T2345_TO_GZ2000_X. */
  Double T2345_TO_GZ2000_X = -374151.464765618;

  /** The constant T2345_TO_GZ2000_Y. */
  Double T2345_TO_GZ2000_Y = -2331890.52174604;

  /** The constant T2345_TO_GZ2000_M. */
  Double T2345_TO_GZ2000_M = -3.59216301315524E-06;

  /** The constant T2345_TO_GZ2000_R. */
  Double T2345_TO_GZ2000_R = 0.00484909724486718;

  /** The constant GZ2000_TO_2435_X. */
  Double GZ2000_TO_2435_X = 385455.970368639;

  /** The constant GZ2000_TO_2435_Y. */
  Double GZ2000_TO_2435_Y = 2330057.18710631;

  /** The constant GZ2000_TO_2435_M. */
  Double GZ2000_TO_2435_M = 3.58872253802822E-06;

  /** The constant GZ2000_TO_2435_R. */
  Double GZ2000_TO_2435_R = -0.00484909724489578;

  /**
   * Bd 09 to gcj 02 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] bd09ToGcj02(Double lng, Double lat);

  /**
   * Bd 09 to wgs 84 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] bd09ToWgs84(Double lng, Double lat);

  /**
   * Bd 09 to gz 2000 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] bd09ToGz2000(Double lng, Double lat);

  /**
   * Gcj 02 to bd 09 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] gcj02ToBd09(Double lng, Double lat);

  /**
   * Gcj 02 to wgs 84 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] gcj02ToWgs84(Double lng, Double lat);

  /**
   * Gcj 02 to gz 2000 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] gcj02ToGz2000(Double lng, Double lat);

  /**
   * Wgs 84 to gcj 02 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] wgs84ToGcj02(Double lng, Double lat);

  /**
   * Wgs 84 to bd 09 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] wgs84ToBd09(Double lng, Double lat);

  /**
   * Wgs 84 to gz 2000 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] wgs84ToGz2000(Double lng, Double lat);

  /**
   * Gz 2000 to wgs 84 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] gz2000ToWgs84(Double lng, Double lat);

  /**
   * Gz 2000 to bd 09 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] gz2000ToBd09(Double lng, Double lat);

  /**
   * Gz 2000 to gcj 02 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  Double[] gz2000ToGcj02(Double lng, Double lat);

  /**
   * Transform lat double.
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double
   */
  default Double transformLat(Double lng, Double lat) {
    lat = +lat;
    lng = +lng;
    double ret =
        -100.0
            + 2.0 * lng
            + 3.0 * lat
            + 0.2 * lat * lat
            + 0.1 * lng * lat
            + 0.2 * Math.sqrt(Math.abs(lng));
    ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
    ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
    ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
    return ret;
  }

  /**
   * Transform lng double.
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double
   */
  default Double transformLng(Double lng, Double lat) {
    lat = +lat;
    lng = +lng;
    double ret =
        300.0
            + lng
            + 2.0 * lat
            + 0.1 * lng * lng
            + 0.1 * lng * lat
            + 0.1 * Math.sqrt(Math.abs(lng));
    ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
    ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
    ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
    return ret;
  }

  /**
   * 判断是否在国内，不在国内则不做偏移
   *
   * @param lng the lng
   * @param lat the lat
   * @return the boolean
   */
  default boolean outOfChina(Double lng, Double lat) {
    lat = +lat;
    lng = +lng;
    // 纬度 3.86~53.55, 经度 73.66~135.05
    return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
  }

  /**
   * Wgs 84 to 2435 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  default Double[] wgs84To2435(Double lng, Double lat) {
    CRSFactory crsFactory = new CRSFactory();
    // 源坐标系统
    String sourceCrs = "wgs84";
    String sourceCrsParams = "+proj=longlat +datum=WGS84 +no_defs ";
    CoordinateReferenceSystem source = crsFactory.createFromParameters(sourceCrs, sourceCrsParams);

    // 目标坐标系统
    String targetCrs = "2435";
    String targetCrsParams =
        "+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=500000 +y_0=0  +towgs84=15.8,-154.4,-82.3 +ellps=krass +units=m +no_defs ";
    CoordinateReferenceSystem target = crsFactory.createFromParameters(targetCrs, targetCrsParams);

    // 定义转换类WGS84转2436
    CoordinateTransformFactory ctf = new CoordinateTransformFactory();
    CoordinateTransform transform = ctf.createTransform(source, target);

    // WGS84坐标系转换
    ProjCoordinate projCoordinate = new ProjCoordinate(lng, lat);
    transform.transform(projCoordinate, projCoordinate);
    double x1 = projCoordinate.x;
    double y1 = projCoordinate.y;
    return new Double[] {x1, y1};
  }

  /**
   * Gz 2000 to 2345 double [ ].
   *
   * @param lng the lng
   * @param lat the lat
   * @return the double [ ]
   */
  default Double[] t2435ToWgs84(Double lng, Double lat) {
    CRSFactory crsFactory = new CRSFactory();
    // 目标坐标系统
    String targetCrs = "wgs84";
    String targetCrsParams = "+proj=longlat +datum=WGS84 +no_defs ";
    CoordinateReferenceSystem target = crsFactory.createFromParameters(targetCrs, targetCrsParams);

    // 源坐标系统
    String sourceCrs = "2435";
    String sourceCrsParams =
        "+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=500000 +y_0=0  +towgs84=15.8,-154.4,-82.3 +ellps=krass +units=m +no_defs ";
    CoordinateReferenceSystem source = crsFactory.createFromParameters(sourceCrs, sourceCrsParams);

    // 定义转换类2436转WGS84
    CoordinateTransformFactory ctf = new CoordinateTransformFactory();
    CoordinateTransform transform = ctf.createTransform(source, target);

    // WGS84坐标系转换
    ProjCoordinate projCoordinate = new ProjCoordinate(lng, lat);
    transform.transform(projCoordinate, projCoordinate);
    double x1 = projCoordinate.x;
    double y1 = projCoordinate.y;
    return new Double[] {x1, y1};
  }
}
